package com.xiashitech.agent.instrumentation.spring.controller_earlier_v3_1;

import com.xiashitech.agent.config.StartConfig;
import com.xiashitech.agent.dto.UserRequest;
import com.xiashitech.agent.instrumentation.base.AbstractAttributesExtractor;
import com.xiashitech.agent.instrumentation.base.context.TraceContextVars;
import com.xiashitech.agent.instrumentation.bridge.Java8Bridge;
import com.xiashitech.agent.instrumentation.utils.BaggageUtil;
import com.xiashitech.agent.instrumentation.utils.MachineAttributesUtil;
import com.xiashitech.agent.utils.XSUtil;
import com.xiashitech.interfaces.agent.dto.AgentConfigDTO;
import com.xiashitech.interfaces.agent.dto.SystemInfoDTO;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.baggage.Baggage;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.context.Context;
import org.jetbrains.annotations.Nullable;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class XSControllerRequestAttributesExtractor extends AbstractAttributesExtractor<UserRequest, HttpServletResponse> {
    public String getAttributesExtractorName() {
        return XSControllerRequestAttributesExtractor.class.getName();
    }

    @Override
    public void onXSStart(AttributesBuilder attributesBuilder, Context context, UserRequest userRequest) {
        Baggage baggage = Baggage.fromContext(context);
        try {
            if ((userRequest.getUserid() == null || "".equals(userRequest.getUserid())) && baggage.size() > 0) {
                userRequest.setUserid(baggage.getEntryValue("xs.userId"));
                userRequest.setRequestDate(baggage.getEntryValue("xs.requestDate"));
                userRequest.setSessionId(baggage.getEntryValue("xs.sessionId"));
                userRequest.setSessionUpdate(baggage.getEntryValue("xs.sessionUpdate") == null ? false : Boolean.valueOf(baggage.getEntryValue("xs.sessionUpdate")));
            }
            if (baggage.size() > 0 && baggage.getEntryValue("xs.loginName") != null) {
                userRequest.setLoginName(baggage.getEntryValue("xs.loginName"));
            }
            if (AgentConfigDTO.getConfig().getCaptureApi() != null && AgentConfigDTO.getConfig().getCaptureApi()) {
                // spring3.1 之前版本不方便获请求对应的Controller元信息，直接从请求中获取API信息
                HttpServletRequest request = (HttpServletRequest) userRequest.getRequest();
                attributesBuilder.put("xs.api.httpMethod", request.getMethod());
                attributesBuilder.put("xs.api.path", request.getRequestURI());
                attributesBuilder.put("xs.api.requestContentType", request.getContentType());

                //根据项目实施情况再看是否需要支持 requestBody 为 json 的情况（获取输入流后再去JSON中提取name）
                //目前支持form参数和path参数
                attributesBuilder.put("xs.api.requestParams", XSUtil.extractParamNamesFromRequest(request.getParameterNames()));

                String endpointApiIsNull = baggage.getEntryValue("endpoint-api");
                if (endpointApiIsNull == null) {
                    String endpointApi = request.getRequestURI();
                    userRequest.setEndpointApi(endpointApi);
                    userRequest.setApiSystemId(StartConfig.getParamValueFromKey(StartConfig.systemId));
                    userRequest.setIsOutApi(Boolean.TRUE);
                }
            }
        } catch (Throwable e) {
            StartConfig.throwableStackPrinter(e);
        }
    }

    @Override
    public void onXSEnd(AttributesBuilder attributesBuilder, Context context, UserRequest userRequest, @Nullable HttpServletResponse response, @Nullable Throwable throwable) {
        if (userRequest != null) {
            try {
                attributesBuilder.put("xs.userId", userRequest.getUserid() == null ? "" : userRequest.getUserid());
                attributesBuilder.put("xs.loginName", userRequest.getLoginName() == null ? "" : userRequest.getLoginName());
                attributesBuilder.put("xs.sessionId", userRequest.getSessionId() == null ? "" : userRequest.getSessionId());
                attributesBuilder.put("xs.requestDate", userRequest.getRequestDate() == null ? "" : userRequest.getRequestDate().toString());
                attributesBuilder.put("xs.sessionUpdate", userRequest.getSessionUpdate() == null ? false : userRequest.getSessionUpdate());
                attributesBuilder.put("xs.systemId", StartConfig.getParamValueFromKey(StartConfig.systemId));
                attributesBuilder.put("xs.systemReg", SystemInfoDTO.getConfig().getSystemExist());
                attributesBuilder.put("xs.sourceSystemId", BaggageUtil.getTraceVar(context, "xsAuthSystemId") == null ? StartConfig.getParamValueFromKey(StartConfig.systemId) : BaggageUtil.getTraceVar(context, "xsAuthSystemId"));
                TraceContextVars.get()
                        .set("xs.sessionUpdate", userRequest.getSessionUpdate() == null ? "false" : userRequest.getSessionUpdate().toString());

                String contentType = response.getContentType();
                attributesBuilder.put("xs.api.responseContentType", contentType);
                // Not implemented earlier spring 3.1
                attributesBuilder.put("xs.api.responseParams", "[]");

                // 说明：脱敏不在这里实现。这里仅负责 SPAN 基础的标签数据采集
                // spring 3.1 之前版本的脱敏移步package /biz/desensitization

            } catch (Throwable e) {
                StartConfig.throwableStackPrinter(e);
            }
        }
        MachineAttributesUtil.fillMachineAttributes(attributesBuilder);
    }
}
